package com.sunck.common.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * Redis 操作工具类
 *
 * @author LengChen
 * @version 1.0
 * @date 2020/8/6
 */
@Component
public class RedisUtils {

    private static final Logger logger = LoggerFactory.getLogger(RedisUtils.class);

    @Autowired
    private  RedisTemplate redisTemplate;

    @Value("${spring.redis.keyPrefix}")
    private String keyPrefix;


    /**
     * 获取缓存所有的key
     * @param key
     * @param <T>
     * @return
     */
    public <T> Set<T> getKeys(String key){
        Set<T> keySet = new HashSet<>();
        try {
            keySet = redisTemplate.keys(key);;
            //logger.debug("getKeys {} = {}", key);
        } catch (Exception e) {
            //logger.warn("getKeys {} = {}", key, e);
            e.printStackTrace();
        }
        return keySet;
    }


    /**
     *  获取缓存
     * @param key 键
     * @return 值
     */
    public <T> T getObject(String key){
        T value = null;
        try {
            value = (T) redisTemplate.opsForValue().get(key);
            //logger.debug("getObject {} = {}", key, value);
        } catch (Exception e) {
           // logger.error("getObject {} = {}", key, value);
            e.printStackTrace();
        }
        return value;
    }

    /**
     * 设置缓存
     * @param key 键
     * @param value 值
     * @param cacheSeconds 超时时间，0为不超时（默认毫秒）
     * @return
     */
    public <T> boolean setObject(String key, T value, int cacheSeconds) {
        boolean result = false;
        try {
            redisTemplate.opsForValue().set(key,value,cacheSeconds, TimeUnit.MILLISECONDS);
            result = true;
           // logger.debug("setObject {} = {}", key, value);
        } catch (Exception e) {
           // logger.warn("setObject {} = {}", key, value, e);
            e.printStackTrace();
        }
        return result;
    }


    /**
     *  设置 List 缓存
     * @param key
     * @param value
     * @param cacheSeconds
     * @param <T>
     * @return
     */
    public <T> boolean setList(String key, List<T> value, int cacheSeconds){
        boolean result = false;
        try {
            if(redisTemplate.hasKey(key)){
                redisTemplate.delete(key);
            }
            redisTemplate.opsForList().rightPushAll(key,value);
            if (cacheSeconds != 0) {
                redisTemplate.expire(key, cacheSeconds,TimeUnit.MILLISECONDS);
            }
            result = true;
           // logger.debug("setList {} = {}", key, value);
        } catch (Exception e) {
           // logger.warn("setList {} = {}", key, value, e);
            e.printStackTrace();
        }
        return result;
    }

    /**
     *  向List中添加值
     * @param key
     * @param value
     * @param cacheSeconds
     * @param <T>
     * @return
     */
    public <T> boolean setList(String key, T value, int cacheSeconds){
        boolean result = false;
        try {
            redisTemplate.opsForList().rightPush(key,value);
            result = true;
            //logger.debug("setList {} = {}", key, value);
        } catch (Exception e) {
            //logger.warn("setList {} = {}", key, value, e);
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 获取List 缓存
     * @param key
     * @return
     */
    public <T> List<T>  getList(String key){
        List<T> value = null;
        try {
            value = redisTemplate.opsForList().range(key,0,-1);
            //logger.debug("getList {} = {}", key, value);
        } catch (Exception e) {
            //logger.error("getList {} = {}", key, value);
            e.printStackTrace();
        }
        return value;
    }

    /**
     * 设置hash值
     * @param key
     * @param value
     * @param cacheSeconds
     * @param <T>
     * @return
     */
    public <T, K> boolean setHashMap(String key, HashMap<K,T> value, int cacheSeconds){
        boolean result = false;
        try {
            if(redisTemplate.hasKey(key)){
                redisTemplate.delete(key);
            }
            redisTemplate.opsForHash().putAll(key,value);
            if (cacheSeconds != 0) {
                redisTemplate.expire(key, cacheSeconds,TimeUnit.MILLISECONDS);
            }
            result = true;
            //logger.debug("setHashMap {} = {}", key, value);
        } catch (Exception e) {
           // logger.warn("setHashMap {} = {}", key, value, e);
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 设置单个map值
     * @param key key值
     * @param mapKey map key
     * @param <T> 值
     * @return
     */
    public <T> boolean setHash(String key,T mapKey, T value){
        boolean result = false;
        try {
            redisTemplate.opsForHash().put(key,mapKey,value);
            result = true;
            //logger.debug("setHash {} = {}", key, value);
        } catch (Exception e) {
            //logger.warn("setHash {} = {}", key, value, e);
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 获取Map缓存
     * @param key
     * @param <T>
     * @return
     */
    public <K , T> Map<K,T> getHash(String key){
        Map<K,T> map = null;
        try {
            map = redisTemplate.opsForHash().entries(key);
            //logger.debug("getHash {} = {}", key);
        } catch (Exception e) {
            //logger.warn("getHash {} = {}", key, e);
            e.printStackTrace();
        }
        return map;
    }

    /**
     *  获取变量中的指定map键是否有值,如果存在该map键则获取值，没有则返回null。
     * @param key
     * @param mapKey
     * @return
     */
    public Object getHashValue(String key ,String mapKey){
        Object object = null;
        try {
            object = redisTemplate.opsForHash().get(key,mapKey);
            //logger.debug("getHashValue {} = {}", key , mapKey);
        } catch (Exception e) {
            //logger.warn("getHashValue {} = {}", key, mapKey, e);
            e.printStackTrace();
        }
        return object;
    }

    /**
     *  获取变量中的指定map键是否有值,如果存在该map键则获取值，没有则返回null。
     * @param key
     * @return
     */
    public int getHashSize(String key){
        int  size = 0;
        try {
            size = redisTemplate.opsForHash().size(key).intValue();
            //logger.debug("getHashSize {} = {}", key, size);
        } catch (Exception e) {
            //logger.warn("getHashSize {} = {}", key, e);
            e.printStackTrace();
        }
        return size;
    }

    /**
     * 获取Hash缓存所有的key
     * @param key
     * @param <T>
     * @return
     */
    public <T> Set<T> getHashKeys(String key){
        Set<T> keySet = new HashSet<>();
        try {
            keySet = redisTemplate.opsForHash().keys(key);;
            //logger.debug("getHashKeys {} = {}", key);
        } catch (Exception e) {
            //logger.warn("getHashKeys {} = {}", key, e);
            e.printStackTrace();
        }
        return keySet;
    }

    /**
     * 获取Hash缓存所有的value
     * @param key
     * @param <T>
     * @return
     */
    public <T> List<T> getHashValues(String key){
        List<T> Values = new ArrayList<>();
        try {
            Values = redisTemplate.opsForHash().values(key);;
           // logger.debug("getHashValues {} = {}", key);
        } catch (Exception e) {
            //logger.warn("getHashValues {} = {}", key, e);
            e.printStackTrace();
        }
        return Values;
    }


    /**
     * 删除变量中的键值对
     * @param key
     * @param mapKey
     * @return
     */
    public <T> boolean removeHashKey(String key, String mapKey){
        boolean result = false;
        try {
            redisTemplate.opsForHash().delete(key,mapKey);
            result = true;
            //logger.debug("removeMapKey {} = {}", key, mapKey);
        } catch (Exception e) {
            //logger.warn("removeMapKey {} = {}", key, mapKey, e);
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 移除缓存
     * @param key
     * @return
     */
    public <T> boolean removeKey(String key){
        boolean result = false;
        try {
            redisTemplate.delete(key);
            result = true;
            //logger.debug("removeKey {} = {}", key);
        } catch (Exception e) {
            //logger.warn("removeKey {} = {}", key, e);
            e.printStackTrace();
        }
        return result;
    }

}
